/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package thread;

import algorithm.BlobAlgorithm;
import algorithm.SkinDetectionAlgorithm;
import drivers.WebcamRSTP;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.beans.PropertyVetoException;
import java.util.logging.Level;
import java.util.logging.Logger;
import recognize.RecognizeObjectsOpenCV;
import structure.StructureBlob;
import transferObject.BlackWhiteImageTO;
import transferObject.BlackWhiteImageToBlobTO;
import transferObject.CamImageTO;
import transferObject.ProcessingImageTO;
import transferObject.ToAlgorithmHAARTO;
import transferObject.ToAlgorithmSkinTO;
import util.Normalization;
import util.Utils;
import view.ViewCameraPanel;

/**
 *
 * @author Progresywny Maciek
 */
public class InstanceThreadRSTP extends ViewCameraPanel implements ViewPanelInterface {

    private WebcamRSTP webcam;
    private CamImageTO camImage;
    private BlackWhiteImageTO blackWhiteImage;
    private ProcessingImageTO processingImage;
    //private RecognizeObjectJJIL recognizeObject;
    private RecognizeObjectsOpenCV recognizeObjectCVFront;
    private RecognizeObjectsOpenCV recognizeObjectCVProfil;
    private BlobAlgorithm blobAlgorithm;
    private StructureBlob structBlobs;
    private SkinDetectionAlgorithm skinDetectionAlgorithm;
    private ToAlgorithmHAARTO toAlgorithmHAAR;
    private ToAlgorithmSkinTO toAlgorithmSkin;
    private BlackWhiteImageToBlobTO blackWhiteImageToBlob;
    private int view = 0;
    //private RecognizeObjectsViolaJones recognizeObjectVJ;
    private int frequence = 25;
    private int brightness = 0;
    private int contrast = 0;
    private int median = 1;
    private int binarization = 0;
    private long detectStartTime = 0;
    private Rectangle[] r;
    private boolean medianFilter = false;
    private boolean algFrontFace = true;
    private boolean algProfilFace = false;
    private boolean algSkinFace = false;

    public InstanceThreadRSTP(String rstp) {
        this.webcam = new WebcamRSTP(rstp);
        this.frequence = 25;
        //this.recognizeObject = new RecognizeObjectJJIL();
        this.recognizeObjectCVFront = new RecognizeObjectsOpenCV();
        this.recognizeObjectCVProfil = new RecognizeObjectsOpenCV();
        //this.recognizeObjectVJ = new RecognizeObjectsViolaJones();
        this.camImage = new CamImageTO();
        this.processingImage = new ProcessingImageTO();
        this.blackWhiteImage = new BlackWhiteImageTO();
        this.blobAlgorithm = new BlobAlgorithm();
        this.structBlobs = new StructureBlob();
        this.toAlgorithmHAAR = new ToAlgorithmHAARTO();
        this.toAlgorithmSkin = new ToAlgorithmSkinTO();
        this.skinDetectionAlgorithm = new SkinDetectionAlgorithm();
        this.blackWhiteImageToBlob = new BlackWhiteImageToBlobTO();
        initInterface();
        if (getOK() == true) {
            t.start();
        } else {
            try {
                super.setClosed(true);
            } catch (PropertyVetoException ex) {
                Logger.getLogger(InstanceThreadRSTP.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    private void initInterface() {
        alg_noiser.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                alg_noiserActionPerformed(evt);
            }
        });

        close.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                closeActionPerformed(evt);
            }
        });

        start.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                startActionPerformed(evt);
            }
        });

        alg_loadFront.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                alg_loadFrontActionPerformed(evt);
            }
        });

        alg_loadProfil.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                alg_loadProfilActionPerformed(evt);
            }
        });

        stop.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                stopActionPerformed(evt);
            }
        });

        par_brightness.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                par_brightnessStateChanged(evt);
            }
        });

        par_contrast.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                par_contrastStateChanged(evt);
            }
        });

        alt_frequence.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                alt_frequenceStateChanged(evt);
            }
        });

        alg_binar.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                alg_binarStateChanged(evt);
            }
        });

        flo_leftSide.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                flo_leftSide(evt);
            }
        });

        flo_rightSide.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                flo_rightSide(evt);
            }
        });

        alg_frontFace.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                alg_frontFaceActionPerformed(evt);
            }
        });

        alg_profilFace.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                alg_profilFaceActionPerformed(evt);
            }
        });

        alg_skinFace.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                alg_skinFaceActionPerformed(evt);
            }
        });

        changeResolution.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                changeResolutionPerformed(evt);
            }
        });

        view1.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                viewStateChanged(evt);
            }
        });
        view2.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                viewStateChanged(evt);
            }
        });
        view3.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                viewStateChanged(evt);
            }
        });
        view4.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                viewStateChanged(evt);
            }
        });
        view5.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                viewStateChanged(evt);
            }
        });

        view6.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                viewStateChanged(evt);
            }
        });

        Dimension d = this.webcam.getSize();
        alg_width.setText(Integer.toString(d.width));
        alg_height.setText(Integer.toString(d.height));

        alg_noise.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                alg_noiseActionPerformed(evt);
            }
        });
    }

    public void closeActionPerformed(java.awt.event.ActionEvent evt) {
        try {
            webcam.closeCamera();
            t.interrupt();
            setClosed(true);
        } catch (PropertyVetoException ex) {
            Logger.getLogger(InstanceThreadUSB.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void alg_loadFrontActionPerformed(java.awt.event.ActionEvent evt) {
        t.suspend();
        this.recognizeObjectCVFront = new RecognizeObjectsOpenCV(alg_cascadeFront.getSelectedItem().toString());
        t.resume();
    }

    public void alg_loadProfilActionPerformed(java.awt.event.ActionEvent evt) {
        t.suspend();
        this.recognizeObjectCVProfil = new RecognizeObjectsOpenCV(alg_cascadeProfil.getSelectedItem().toString());
        t.resume();
    }

    public void startActionPerformed(java.awt.event.ActionEvent evt) {
        t.resume();
    }

    public void alg_noiserActionPerformed(java.awt.event.ActionEvent evt) {
        median = Integer.parseInt(alg_noiser.getSelectedItem().toString());
        System.out.println(median);
    }

    public void stopActionPerformed(java.awt.event.ActionEvent evt) {
        t.suspend();
    }

    public void par_brightnessStateChanged(javax.swing.event.ChangeEvent evt) {
        brightness = par_brightness.getValue();
    }

    public void par_contrastStateChanged(javax.swing.event.ChangeEvent evt) {
        contrast = par_contrast.getValue();
    }

    public void alt_frequenceStateChanged(javax.swing.event.ChangeEvent evt) {
        frequence = alt_frequence.getValue();
        alg_fps.setText(alt_frequence.getValue() + " fps");
    }

    public void alg_binarStateChanged(javax.swing.event.ChangeEvent evt) {
        binarization = alg_binar.getValue();
    }

    public void flo_leftSide(javax.swing.event.ChangeEvent evt) {
        System.out.println("da");
    }

    public void flo_rightSide(javax.swing.event.ChangeEvent evt) {
        System.out.println("da");
    }

    public void alg_frontFaceActionPerformed(java.awt.event.ActionEvent evt) {
        if (algFrontFace == false) {
            algFrontFace = true;
        } else {
            algFrontFace = false;
        }
    }

    public void alg_profilFaceActionPerformed(java.awt.event.ActionEvent evt) {
        if (algProfilFace == false) {
            algProfilFace = true;
        } else {
            algProfilFace = false;
        }
    }

    public void alg_skinFaceActionPerformed(java.awt.event.ActionEvent evt) {
        if (algSkinFace == false) {
            algSkinFace = true;
        } else {
            algSkinFace = false;
        }
    }

    public void changeResolutionPerformed(java.awt.event.ActionEvent evt) {
        if ((alg_width.getValue() == 176 || alg_width.getValue() == 320 || alg_width.getValue() == 640) && (alg_height.getValue() == 144 || alg_height.getValue() == 240 || alg_height.getValue() == 480)) {
            t.suspend();
            webcam.closeCamera();
            webcam.setSize(Integer.parseInt(alg_width.getValue().toString()), Integer.parseInt(alg_height.getValue().toString()));
            webcam.openCamera();
            t.resume();
        } else {
        }
    }

    public void alg_noiseActionPerformed(java.awt.event.ActionEvent evt) {
        if (medianFilter == false) {
            medianFilter = true;
        } else {
            medianFilter = false;
        }
    }

    private void viewStateChanged(javax.swing.event.ChangeEvent evt) {
        if (view1.isSelected() == true) {
            view = 0;
        }
        if (view2.isSelected() == true) {
            view = 1;
        }
        if (view3.isSelected() == true) {
            view = 2;
        }
        if (view4.isSelected() == true) {
            view = 3;
        }
        if (view5.isSelected() == true) {
            view = 4;
        }
        if (view6.isSelected() == true) {
            view = 5;
        }
    }

    public boolean getOK() {
        return webcam.mPlayer.isPlaying();
    }
    public Thread t = new Thread(new Runnable() {
        public void run() {
            while (true) {
                try {
                    detectStartTime = System.currentTimeMillis();
                    
                    camImage.setFrame(webcam.getOneFrame().getFrame());
                      if (view == 0) {

                        p.setImage(camImage.getFrame());
                        p.repaintImage();
                    }

                    processingImage.setFrame(camImage.getFrame());
                    //processingImage.preprocessing(brightness, contrast);

                    if (view == 1) {
                        p.setImage(processingImage.getFrame());
                        p.repaintImage();
                    }

                    //1 Detekcja HAAR tylko
                    if ((algFrontFace == true || algProfilFace == true) && algSkinFace == false) {
                        if (algFrontFace == true && algProfilFace == false) {
                            r = recognizeObjectCVFront.recognize(processingImage.getFrame());
                            blackWhiteImage.getBlackWhite(r, processingImage.getWidth(), processingImage.getHeight());
                            structBlobs = blobAlgorithm.getBlobs(blackWhiteImage.getFrame());  
                        }
                        if (algProfilFace == true && algFrontFace == false) {
                            r = recognizeObjectCVProfil.recognize(processingImage.getFrame());
                            blackWhiteImage.getBlackWhite(r, processingImage.getWidth(), processingImage.getHeight());
                            structBlobs = blobAlgorithm.getBlobs(blackWhiteImage.getFrame());    
                        }
                        if (algFrontFace == true && algProfilFace == true) {
                            r = recognizeObjectCVFront.recognize(processingImage.getFrame());
                            if (r == null) {
                                r = recognizeObjectCVProfil.recognize(processingImage.getFrame());
                            }
                            blackWhiteImage.getBlackWhite(r, processingImage.getWidth(), processingImage.getHeight());
                            structBlobs = blobAlgorithm.getBlobs(blackWhiteImage.getFrame());     
                        }
                    } else {
                        r = null;
                    }

                    //2 Detekcja Skin tylko
                    if (algSkinFace == true && algFrontFace == false && algProfilFace == false) {
                        if (medianFilter == true) {
                            toAlgorithmSkin.setFrame(skinDetectionAlgorithm.detect(processingImage.getFrame()));
                            blackWhiteImageToBlob.setFrame(Utils.getMedianSkinToBlackWhite(Normalization.MedianFilter(Utils.getSkinToBlackWhite(toAlgorithmSkin.getFrame()), median)));
                        } else {
                            toAlgorithmSkin.setFrame(skinDetectionAlgorithm.detect(processingImage.getFrame()));
                            blackWhiteImageToBlob.setFrame(Utils.getMedianSkinToBlackWhite(Utils.getSkinToBlackWhite(toAlgorithmSkin.getFrame())));
                        }
                        structBlobs = blobAlgorithm.getBlobs(blackWhiteImageToBlob.getFrame());
                    }

                    //3 Mix detekcja Skin i Haar
                    if ((algFrontFace == true || algProfilFace == true) && algSkinFace == true) {
                        if (algFrontFace == true && algProfilFace == false) {
                            r = recognizeObjectCVFront.recognize(processingImage.getFrame());
                        }
                        if (algProfilFace == true && algFrontFace == false) {
                            r = recognizeObjectCVProfil.recognize(processingImage.getFrame());
                        }
                        if (algFrontFace == true && algProfilFace == true) {
                            r = recognizeObjectCVFront.recognize(processingImage.getFrame());
                            if (r == null) {
                                r = recognizeObjectCVProfil.recognize(processingImage.getFrame());
                            }
                        }
                        if (medianFilter == true) {
                            toAlgorithmSkin.setFrame(skinDetectionAlgorithm.detect(processingImage.getFrame()));
                            blackWhiteImage.getBlackWhite(r, processingImage.getWidth(), processingImage.getHeight());
                            blackWhiteImageToBlob.setFrame(Utils.getImageAndImage(blackWhiteImage.getFrame(), Utils.getMedianSkinToBlackWhite(Normalization.MedianFilter(Utils.getSkinToBlackWhite(toAlgorithmSkin.getFrame()), median))));
                        } else {
                            toAlgorithmSkin.setFrame(skinDetectionAlgorithm.detect(processingImage.getFrame()));
                            blackWhiteImage.getBlackWhite(r, processingImage.getWidth(), processingImage.getHeight());
                            blackWhiteImageToBlob.setFrame(Utils.getImageAndImage(blackWhiteImage.getFrame(), Utils.getSkinToBlackWhite(toAlgorithmSkin.getFrame())));
                        }
                        structBlobs = blobAlgorithm.getBlobs(blackWhiteImageToBlob.getFrame());
                    }


                    if (view == 2) {
                        if (algFrontFace == false && algProfilFace == false && algSkinFace == true) {
                            p.setImage(toAlgorithmSkin.getFrame());
                        }
                        if ((algFrontFace == true || algProfilFace == true) && algSkinFace == false) {
                            p.setImage(processingImage.getFrame());
                            p.setRectagles(r);
                        }
                        p.repaintImage();
                    }


                    if (view == 3) {
                        if ((algFrontFace == true || algProfilFace == true) && algSkinFace == true ) {
                            p.setImage(blackWhiteImageToBlob.getFrame());
                        } 
                        if ((algFrontFace == true || algProfilFace == true) && algSkinFace == false) {
                            p.setImage(blackWhiteImage.getFrame());
                        } 
                        if (algSkinFace == true && algFrontFace == false && algProfilFace == false) {
                            p.setImage(blackWhiteImageToBlob.getFrame());
                        }
                        p.repaintImage();
                    }


                    if (view == 4) {
                        p.setImage(structBlobs.getImage());
                        p.repaintImage();
                    }
                    Thread.sleep(Utils.ftpsToMilisecond(frequence));
                    long detectDuration = System.currentTimeMillis() - detectStartTime;
                    alg_real_fps.setText(Integer.toString(Utils.milisecondToFtps(detectDuration)) + " fps");
                } catch (InterruptedException ex) {
                    Logger.getLogger(InstanceThreadUSB.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    });

    public static void main(String[] args) {
    }
}
